MaterialUI使ってみる


概要

このページを参考に動かしてみる。

http://blog.takanabe.tokyo/2015/12/11/1778/


最終的には、左右のペーン、右ペーン内にリストで項目表示、みたいな画面が作りたい。



プロジェクトつくる

まずはnpm管理下のプロジェクトを作成。

mkdir mat

cd mat 

npm init


package.jsonに次を記載

{

  "name": "mat",

  "version": "1.0.0",

  "description": "",

  "main": "index.js",

  "scripts": {

    "test": "echo \"Error: no test specified\" && exit 1",

    "start": "webpack-dev-server --hot --inline --progress --colors",

    "build": "webpack --progress --colors"

  },

  "devDependencies": {

    "babel-core": "^5.8.25",

    "babel-eslint": "^4.1.3",

    "babel-loader": "^5.3.2",

    "babel-runtime": "^5.8.25",

    "css-loader": "^0.19.0",

    "eslint": "^1.6.0",

    "eslint-loader": "^1.1.0",

    "eslint-plugin-react": "^3.5.1",

    "fbjs": "^0.2.1",

    "file-loader": "^0.8.4",

    "style-loader": "^0.12.4",

    "webpack": "^1.12.2",

    "webpack-dev-server": "^1.12.0",

    "webpack-hot-middleware": "^2.2.0"

  },

    "dependencies": {

    "classnames": "^2.1.2",

    "fbjs": "^0.3.2",

    "material-ui": "^0.13.0",

    "react": "^0.14.0",

    "react-addons-create-fragment": "^0.14.0",

    "react-addons-pure-render-mixin": "^0.14.0",

    "react-addons-transition-group": "^0.14.0",

    "react-addons-update": "^0.14.0",

    "react-dom": "^0.14.0",

    "react-hot-loader": "^1.3.0",

    "react-redux": "^3.1.0",

    "react-tap-event-plugin": "^0.2.0",

    "redux": "^3.0.2"

  },

  "author": "",

  "license": "ISC"

}


で、

npm install


次に、webpack.config.jsを作成して、、いろいろ書きこむ。

module.exports = {

  context: __dirname,

  entry: {

    jsx: "./src/index.jsx",

    css: "./src/main.css",

    html: "./src/index.html",

  },


  output: {

    path: __dirname + "/static",

    filename: "bundle.js",

  },

  module: {

    preLoaders: [

        //Eslint loader

      { test: /\.jsx?$/, exclude: /node_modules/, loader: "eslint-loader"},

    ],

    loaders: [

      { test: /\.html$/, loader: "file?name=[name].[ext]" },

      { test: /\.css$/, loader: "file?name=[name].[ext]" },

      { test: /\.jsx?$/, exclude: /node_modules/, loaders: ["react-hot","babel-loader"]},

    ],

  },

  resolve: {

    extensions: ['', '.js', '.jsx']

  },

  eslint: {

    configFile: './.eslintrc'

  },

};

eslintって何、ってなってるけどとりあえずやってみる。

touch .eslintrc


{

  "env": {

    "es6": true,

    "browser": true,

    "node": true

  },

  "rules": {

    "curly": 0,

    "comma-dangle": [2, "never"],

    "comma-spacing": 0,

    "eqeqeq": [2, "allow-null"],

    "key-spacing": 0,

    "no-underscore-dangle": 0,

    "no-unused-expressions": 0,

    "no-shadow": 0,

    "no-shadow-restricted-names": 0,

    "no-extend-native": 0,

    "no-var": 2,

    "new-cap": 0,

    "quotes": 0,

    "semi-spacing": 0,

    "space-unary-ops": 0,

    "space-infix-ops": 0,

    "consistent-return": 0,

    "strict": 0

  },

  "parser": "babel-eslint",

  "plugins": [

    "react"

  ],

  "ecmaFeatures": {

    "arrowFunctions": true,

    "jsx": true

  }

}


ああ、babel、、なるほど、、コンパイラの起動とかの設定なのか。概念としてはlint、っていう。


srcフォルダを作って、中にindex.htmlとか置く

mkdir src

touch ./src/index.html

touch ./src/index.jsx

touch ./src/main.css


で、npm run buildで、package.jsonで指定したbuildコマンドを実行。

npm run build


おお、、なんかコンパイルできたぞ、、


で、次に、index.jsxにいろいろ書いたりするんだけど、だいたいかいてあるまま進められる。


ただそのままだと動かなかったので、App.jsxだけ手を加えた。

import React, { Component, PropTypes } from "react";

import { bindActionCreators } from 'redux';

import { connect } from 'react-redux';

import Header from '../components/Header';

import MainSection from '../components/MainSection';


class App extends Component {

  render() {

    return (

      <div>

        <Header />

        <MainSection />

      </div>

    );

  }

}


export default App;


Material UIの作成は、componentsフォルダを作っていろいろファイル置いて、そこにReactComponentを記述しがてら行う。

mkdir components

touch ./components/Header.jsx

touch ./components/MainSection.jsx


Header.jsx

import React, { PropTypes, Component } from 'react';


import mui, {AppBar} from 'material-ui';

const ThemeManager = require('material-ui/lib/styles/theme-manager');

import MyRawTheme from '../src/material_ui_raw_theme_file'


class Header extends Component {

  static get childContextTypes() {

    return { muiTheme: React.PropTypes.object };

  }


  getChildContext(){

    return {  muiTheme: ThemeManager.getMuiTheme(MyRawTheme)};

  }


  render() {

    return (

      <header className="header">

        <h1>AppBar Component</h1>

        <AppBar title="React + Redux + Material UI Boilerplate" />

      </header>

    );

  }

}


export default Header;


これでAppBarが出る。ほうほう。

細かい設定値はちょっと濃い行で、ファイルを使って指定している。

(面倒なのでオフってみた。)


次に、MainSection.jsx

import React, { Component, PropTypes } from 'react';

import mui, {CircularProgress,

             Tabs,

             Tab,

             DatePicker

            } from 'material-ui';


class MainSection extends Component {

  render() {

    return (

      <div>

        <h1>Progress Component</h1>

        <CircularProgress mode="indeterminate" size={1.5} />

        <CircularProgress mode="indeterminate" color={"red"} size={2} />

        <br/>


        <h1>Tab Component</h1>

        <Tabs>

          <Tab label="Tab One" value="0" />

          <Tab label="Tab Two" value="1" />

          <Tab label="Tab Three" value="2" />

        </Tabs>

        <br/>


        <h1>DatePicker Component</h1>

        <DatePicker hintText="Portrait Dialog" />

        <br/>

      </div>

    );

  }

}


export default MainSection;


で、ここまで書いたあと、npm start すると、ウォッチ状態になる + サーバ起動して、ブラウザで観れるようになる。

npm start

スクリーンショット 2016-09-07 15.02.45.png


とりあえず2016/09/07現在でも動いてくれてよかった。


reduxって一体なにで、何してるんだろう、っていうのを後で追う。



MaterialUIでテーブルを表示してみる

http://www.material-ui.com/#/components/table から、

コードを見る(<>マークを押す) -> components フォルダにTableExampleSimple.jsxっていう名前でファイルを作る。


import React from 'react';

import {Table, TableBody, TableHeader, TableHeaderColumn, TableRow, TableRowColumn} from 'material-ui';// 末尾を'material-ui'に変更してパスを合わせてる


const TableExampleSimple = () => (

  <Table>

    <TableHeader>

      <TableRow>

        <TableHeaderColumn>ID</TableHeaderColumn>

        <TableHeaderColumn>Name</TableHeaderColumn>

        <TableHeaderColumn>Status</TableHeaderColumn>

      </TableRow>

    </TableHeader>

    <TableBody>

      <TableRow>

        <TableRowColumn>1</TableRowColumn>

        <TableRowColumn>John Smith</TableRowColumn>

        <TableRowColumn>Employed</TableRowColumn>

      </TableRow>

      <TableRow>

        <TableRowColumn>2</TableRowColumn>

        <TableRowColumn>Randal White</TableRowColumn>

        <TableRowColumn>Unemployed</TableRowColumn>

      </TableRow>

      <TableRow>

        <TableRowColumn>3</TableRowColumn>

        <TableRowColumn>Stephanie Sanders</TableRowColumn>

        <TableRowColumn>Employed</TableRowColumn>

      </TableRow>

      <TableRow>

        <TableRowColumn>4</TableRowColumn>

        <TableRowColumn>Steve Brown</TableRowColumn>

        <TableRowColumn>Employed</TableRowColumn>

      </TableRow>

    </TableBody>

  </Table>

);


export default TableExampleSimple;

で、export句てのがあるのに初めて気づいた。ほう。


containersフォルダのApp.jsx側を以下のように変更

import React, { Component, PropTypes } from "react";

import { bindActionCreators } from 'redux';

import { connect } from 'react-redux';

import Header from '../components/Header';

import MainSection from '../components/MainSection';

import TableExampleSimple from '../components/TableExampleSimple'


class App extends Component {

        // <Header />

        // <MainSection />

  render() {

    return (

      <div>

      <TableExampleSimple />

      </div>

    );

  }

}


export default App;


import句で、コンポーネントの要素 from ファイルパス みたいに指定できるんだな。なるほど。

で、App コンポーネントはUIの根っことして、index.jsxから参照されている。

import React from "react";

import ReactDOM from "react-dom";

import injectTapEventPlugin from "react-tap-event-plugin";


import App from '../containers/App';


//Needed for React Developer Tools

window.React = React;


//Needed for onTouchTap

//Can go away when react 1.0 release

//Check this repo:

//https://github.com/zilverline/react-tap-event-plugin

injectTapEventPlugin();


ReactDOM.render(

  <App />,

  document.getElementById("root")

);


色つきの部分での接続はこういう理屈になってたんだなーー把握。

表示はこんな風になった。


スクリーンショット 2016-09-07 17.16.00.png


で、これあの、、手でJSXに書き直さないといけないの?

TableExampleSimple.jsx

import React from 'react';

import {Table, TableBody, TableHeader, TableHeaderColumn, TableRow, TableRowColumn} from 'material-ui';



const TableExampleSimple = () => (

  <Table>

    <TableHeader>

      <TableRow>

        <TableHeaderColumn>ID</TableHeaderColumn>

        <TableHeaderColumn>Name</TableHeaderColumn>

        <TableHeaderColumn>Status</TableHeaderColumn>

      </TableRow>

    </TableHeader>

    <TableBody>

      <TableRow>

        <TableRowColumn>1</TableRowColumn>

        <TableRowColumn>John Smith</TableRowColumn>

        <TableRowColumn>Employed</TableRowColumn>

      </TableRow>

      <TableRow>

        <TableRowColumn>2</TableRowColumn>

        <TableRowColumn>Randal White</TableRowColumn>

        <TableRowColumn>Unemployed</TableRowColumn>

      </TableRow>

      <TableRow>

        <TableRowColumn>3</TableRowColumn>

        <TableRowColumn>Stephanie Sanders</TableRowColumn>

        <TableRowColumn>Employed</TableRowColumn>

      </TableRow>

      <TableRow>

        <TableRowColumn>4</TableRowColumn>

        <TableRowColumn>Steve Brown</TableRowColumn>

        <TableRowColumn>Employed</TableRowColumn>

      </TableRow>

    </TableBody>

  </Table>

);


export default TableExampleSimple;



UIの表示してるプロジェクトと、nodeのプロジェクトをどうマージするか

ぶっちゃけ通信周りとかはnodeのほうが取り回しが楽なんだけど、package.jsonにあるような要素の中から、webpackとreduxを省いても

無事にjsxからコードが生成できると思うのだがどうか、、まあ今回は無理かな。



exportの別の書き方

こんな風に書くこともできた。

import React, { Component, PropTypes } from "react";

import {TextField} from 'material-ui';


export default class TextFieldExampleSimple extends Component {

  render() {

    return (

      <div>

        <TextField

          hintText="+-> lua codes for devices here."

          multiLine={true}

          rows={3}

          rowsMax={10}

          fullWidth={true}

        />

      </div>

    );

  }

}


用途に応じてって感じかな。



reduxって何で何してんの

react-reduxとreduxがそれぞれ依存(package.json)にあって、

つづく。